import urllib.request
import urllib.error
import json
import os
from datetime import datetime
import glob
import ctypes
from plyer import notification
import time
import module.logger as logger
import re


"""
windows下桌面解锁时自动更换桌面壁纸的工具
"""

log = logger.get_logger()

# 图片存储路径
wallpaper_img_path = "%USERPROFILE%/Pictures/LdWallpapers"


def fetch_wallpaper_json_data(url):
    """获取指定URL的JSON数据"""
    try:
        with urllib.request.urlopen(url) as response:
            response_data = response.read()
            return json.loads(response_data)
    except (
        urllib.error.HTTPError,
        urllib.error.URLError,
        json.JSONDecodeError,
        Exception,
    ) as e:
        log.error(f"请求{url}时出错: {str(e)}")
        raise


def parse_qzink_data(data):
    """解析第一个URL（qzink.me）的JSON格式"""
    try:
        json_data = {
            "title": data.get("title"),
            "img_url": data.get("landscape_url"),
        }
        if not json_data.get("img_url").strip():
            raise ValueError("壁纸URL为空")
        return json_data

    except Exception as e:
        log.error(f"解析数据异常: {str(e)}")
        raise


def parse_bing_data(data):
    """解析第二个URL（bing.fullpx.com）的JSON格式"""
    try:
        json_data = {
            "title": data.get("data").get("title"),
            "img_url": data.get("data").get("fhdUrl"),
        }
        if json_data.get("img_url").endswith(".webp"):
            raise Exception("图片类型错误")
        elif not json_data.get("img_url").strip():
            raise ValueError("壁纸URL为空")
        return json_data
    except Exception as e:
        log.error(f"解析数据异常: {str(e)}")
        raise


def parse_microsoft_data(data):
    """从微软接口获取高清壁纸"""
    try:
        res_data = json.loads(data.get("batchrsp").get("items")[0].get("item"))
        json_data = {
            "title": res_data.get("ad").get("title"),
            "img_url": res_data.get("ad").get("landscapeImage").get("asset"),
        }
        if not json_data.get("img_url").strip():
            raise ValueError("壁纸URL为空")
        return json_data
    except Exception as e:
        log.error(f"解析数据异常: {str(e)}")
        raise


def download_image(url, save_dir, file_name):
    # 从指定URL下载图片并保存到指定目录中
    try:
        # 确保目录存在，不存在则创建
        os.makedirs(save_dir, exist_ok=True)
        file_path = os.path.join(save_dir, file_name)
        # 下载并保存图片
        urllib.request.urlretrieve(url, file_path)
        log.info(f"图片已保存至 {file_path}")

    except Exception as e:
        log.error(f"壁纸下载失败: {str(e)}")
        raise


def set_windows_wallpaper(image_path):
    """
    设置Windows桌面背景图片
    :param image_path: 图片文件的完整路径
    :return: 成功返回True，失败返回False
    """
    # 检查图片文件是否存在
    if not os.path.isfile(image_path):
        log.error(f"错误：图片文件不存在 - {image_path}")
        return False

    # 确保路径是绝对路径
    absolute_path = os.path.abspath(image_path)

    # 调用Windows API设置壁纸
    # SPI_SETDESKWALLPAPER = 20
    # SPIF_UPDATEINIFILE = 1
    result = ctypes.windll.user32.SystemParametersInfoW(
        20,  # 功能代号：设置桌面壁纸
        0,  # 保留参数，设为0
        absolute_path,  # 图片路径
        1,  # 更新用户配置文件
    )

    if result:
        log.info(f"成功设置桌面背景：{absolute_path}")
        return True
    else:
        log.error(f"设置桌面背景失败：{absolute_path}")
        return False


def send_notification(title, message, duration=5):
    """发送系统原生通知（Windows右下角气泡样式）"""
    notification.notify(
        title=title,  # 通知标题
        message=message,  # 通知内容
        app_name="通知",  # 应用名称（显示在通知中）
        timeout=duration,  # 显示时长（秒）
    )
    # 等待通知显示完成（避免程序提前退出）
    time.sleep(duration)


def clean_old_img():
    # 清理并只保留10张图片
    save_img_num = 10
    # 获取文件夹中所有的文件
    img_save_dir = os.path.expandvars(wallpaper_img_path)
    image_files = glob.glob(os.path.join(img_save_dir, "*"))

    # 使用正则过滤图片文件,[一-龥]表示所有汉字
    regex_pattern = r"\.(jpg|jpeg|png)$"
    regex = re.compile(regex_pattern)
    matching_files = list(
        filter(lambda file: regex.search(file) is not None, image_files)
    )
    # 按文件创建时间对图片文件进行排序（最新的在最后）
    matching_files.sort(key=lambda x: os.path.getctime(x))

    # 如果图片数量超过 10 张，删除多余的（保留最新的 10 张）
    if len(matching_files) > save_img_num:
        # 需要删除的文件列表（除了最后 10 个）
        files_to_delete = matching_files[:-save_img_num]
        for file in files_to_delete:
            try:
                os.remove(file)
                log.info(f"已删除文件: {file}")
            except Exception as e:
                log.error(f"删除文件 {file} 时出错: {e}")
        log.info(f"清理完成，保留最新的 {save_img_num} 张图片")
    else:
        log.info(f"图片数量[{len(matching_files)}]不超过 {save_img_num} 张，无需清理")


def main():
    """加载并解析壁纸数据，处理不同格式"""
    # 定义数据源及对应的解析函数
    data_sources = [
        {
            "url": "https://api.qzink.me/spotlight",
            "parser": parse_qzink_data,
            "name": "api.qzink.me",
        },
        {
            "url": "https://bing.fullpx.com/bing/today",
            "parser": parse_bing_data,
            "name": "bing.fullpx.com",
        },
        {
            "url": "https://fd.api.iris.microsoft.com/v4/api/selection?placement=88000820&bcnt=1&fmt=json&locale=zh-CN&country=CN",
            "parser": parse_microsoft_data,
            "name": "fd.api.iris.microsoft.com",
        },
    ]

    for source in data_sources:
        try:
            # 获取原始数据
            raw_data = fetch_wallpaper_json_data(source["url"])
            if not raw_data:
                log.warning(f"从{source['name']}没有请求到有效数据")
                continue

            # 使用对应解析器处理
            parsed_data = source["parser"](raw_data)
            log.info(f"成功从{source['name']}获取并解析壁纸数据")

            img_title = parsed_data.get("title")
            img_url = parsed_data.get("img_url")
            log.info(f"标题: {img_title}")
            log.info(f"图片URL: {img_url}")

            # 清理文件名，移除Windows系统不允许的特殊字符
            # Windows不允许的字符: \ / : * ? " < > |

            # 定义Windows文件名中不允许的字符正则表达式
            illegal_chars = r'[\\/:*?"<>|]'
            # 替换非法字符为空字符串
            img_title = re.sub(illegal_chars, "", img_title)
            # 可以选择去除首尾空白字符
            img_title = img_title.strip()

            # 解析环境变量（如 %USERPROFILE%）为实际路径
            save_dir = os.path.expandvars(wallpaper_img_path)
            img_suffix = img_url.split(".")[-1]

            # 判断是否已下载
            pattern = f"*_{img_title}.{img_suffix}"
            search_pattern = os.path.join(save_dir, pattern)
            # 查找所有匹配的文件（返回完整路径）
            search_result = glob.glob(search_pattern)
            if len(search_result) > 0:
                log.warning(f"该壁纸图片已经下载:{search_result}")
                send_notification(
                    title="壁纸更新失败",
                    message=f"当前【{img_title}】为最新壁纸，请稍后再试",
                )
            else:
                file_name = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{img_title}.{img_suffix}"
                # 下载壁纸
                download_image(img_url, save_dir, file_name)
                log.info("壁纸已经下载成功")

                set_windows_wallpaper(os.path.join(save_dir, file_name))

                send_notification(
                    title="壁纸更新完成", message=f"当前壁纸：{img_title}"
                )
                clean_old_img()
            log.info("=" * 50)

            break

        except Exception as e:
            log.error(f"处理{source['name']}数据失败: {str(e)}")
            # 如果是最后一个数据源失败，则返回None
            if source == data_sources[-1]:
                log.info("所有数据源均处理失败")
